home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / dpmigcc5.zip / RSX / SOURCE / FPU-EMU / REG_U_AD.S < prev    next >
Text File  |  1994-05-27  |  4KB  |  190 lines

  1.     .file    "reg_u_add.S"
  2. /*---------------------------------------------------------------------------+
  3.  |  reg_u_add.S                                                              |
  4.  |                                                                           |
  5.  | Add two valid (TW_Valid) FPU_REG numbers, of the same sign, and put the   |
  6.  |   result in a destination FPU_REG.                                        |
  7.  |                                                                           |
  8.  | Copyright (C) 1992,1993                                                   |
  9.  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
  10.  |                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au    |
  11.  |                                                                           |
  12.  | Call from C as:                                                           |
  13.  |   void reg_u_add(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ,             |
  14.  |                                                int control_w)             |
  15.  |                                                                           |
  16.  +---------------------------------------------------------------------------*/
  17.  
  18. /*
  19.  |    Kernel addition routine reg_u_add(reg *arg1, reg *arg2, reg *answ).
  20.  |    Takes two valid reg f.p. numbers (TW_Valid), which are
  21.  |    treated as unsigned numbers,
  22.  |    and returns their sum as a TW_Valid or TW_S f.p. number.
  23.  |    The returned number is normalized.
  24.  |    Basic checks are performed if PARANOID is defined.
  25.  */
  26.  
  27. #include "exception.h"
  28. #include "fpu_asm.h"
  29. #include "control_w.h"
  30.  
  31. .text
  32.     .align 2,144
  33. .globl _reg_u_add
  34. _reg_u_add:
  35.     pushl    %ebp
  36.     movl    %esp,%ebp
  37.     pushl    %esi
  38.     pushl    %edi
  39.     pushl    %ebx
  40.  
  41.     movl    PARAM1,%esi        /* source 1 */
  42.     movl    PARAM2,%edi        /* source 2 */
  43.  
  44. #ifdef DENORM_OPERAND
  45.     cmpl    EXP_UNDER,EXP(%esi)
  46.     jg    xOp1_not_denorm
  47.  
  48.     call    _denormal_operand
  49.     orl    %eax,%eax
  50.     jnz    fpu_Arith_exit
  51.  
  52. xOp1_not_denorm:
  53.     cmpl    EXP_UNDER,EXP(%edi)
  54.     jg    xOp2_not_denorm
  55.  
  56.     call    _denormal_operand
  57.     orl    %eax,%eax
  58.     jnz    fpu_Arith_exit
  59.  
  60. xOp2_not_denorm:
  61. #endif DENORM_OPERAND
  62.  
  63.     movl    EXP(%esi),%ecx
  64.     subl    EXP(%edi),%ecx        /* exp1 - exp2 */
  65.     jge    L_arg1_larger
  66.  
  67.     /* num1 is smaller */
  68.     movl    SIGL(%esi),%ebx
  69.     movl    SIGH(%esi),%eax
  70.  
  71.     movl    %edi,%esi
  72.     negw    %cx
  73.     jmp    L_accum_loaded
  74.  
  75. L_arg1_larger:
  76.     /* num1 has larger or equal exponent */
  77.     movl    SIGL(%edi),%ebx
  78.     movl    SIGH(%edi),%eax
  79.  
  80. L_accum_loaded:
  81.     movl    PARAM3,%edi        /* destination */
  82. /*    movb    SIGN(%esi),%dl
  83.     movb    %dl,SIGN(%edi) */    /* Copy the sign from the first arg */
  84.  
  85.  
  86.     movl    EXP(%esi),%edx
  87.     movl    %edx,EXP(%edi)        /* Copy exponent to destination */
  88.  
  89.     xorl    %edx,%edx        /* clear the extension */
  90.  
  91. #ifdef PARANOID
  92.     testl    $0x80000000,%eax
  93.     je    L_bugged
  94.  
  95.     testl    $0x80000000,SIGH(%esi)
  96.     je    L_bugged
  97. #endif PARANOID
  98.  
  99. /* The number to be shifted is in %eax:%ebx:%edx */
  100.     cmpw    $32,%cx        /* shrd only works for 0..31 bits */
  101.     jnc    L_more_than_31
  102.  
  103. /* less than 32 bits */
  104.     shrd    %cl,%ebx,%edx
  105.     shrd    %cl,%eax,%ebx
  106.     shr    %cl,%eax
  107.     jmp    L_shift_done
  108.  
  109. L_more_than_31:
  110.     cmpw    $64,%cx
  111.     jnc    L_more_than_63
  112.  
  113.     subb    $32,%cl
  114.     jz    L_exactly_32
  115.  
  116.     shrd    %cl,%eax,%edx
  117.     shr    %cl,%eax
  118.     orl    %ebx,%ebx
  119.     jz    L_more_31_no_low    /* none of the lowest bits is set */
  120.  
  121.     orl    $1,%edx            /* record the fact in the extension */
  122.  
  123. L_more_31_no_low:
  124.     movl    %eax,%ebx
  125.     xorl    %eax,%eax
  126.     jmp    L_shift_done
  127.  
  128. L_exactly_32:
  129.     movl    %ebx,%edx
  130.     movl    %eax,%ebx
  131.     xorl    %eax,%eax
  132.     jmp    L_shift_done
  133.  
  134. L_more_than_63:
  135.     cmpw    $65,%cx
  136.     jnc    L_more_than_64
  137.  
  138.     movl    %eax,%edx
  139.     orl    %ebx,%ebx
  140.     jz    L_more_63_no_low
  141.  
  142.     orl    $1,%edx
  143.     jmp    L_more_63_no_low
  144.  
  145. L_more_than_64:
  146.     movl    $1,%edx        /* The shifted nr always at least one '1' */
  147.  
  148. L_more_63_no_low:
  149.     xorl    %ebx,%ebx
  150.     xorl    %eax,%eax
  151.  
  152. L_shift_done:
  153.     /* Now do the addition */
  154.     addl    SIGL(%esi),%ebx
  155.     adcl    SIGH(%esi),%eax
  156.     jnc    L_round_the_result
  157.  
  158.     /* Overflow, adjust the result */
  159.     rcrl    $1,%eax
  160.     rcrl    $1,%ebx
  161.     rcrl    $1,%edx
  162.     jnc    L_no_bit_lost
  163.  
  164.     orl    $1,%edx
  165.  
  166. L_no_bit_lost:
  167.     incl    EXP(%edi)
  168.  
  169. L_round_the_result:
  170.     jmp    fpu_reg_round    /* Round the result */
  171.  
  172.  
  173.  
  174. #ifdef PARANOID
  175. /* If we ever get here then we have problems! */
  176. L_bugged:
  177.     pushl    EX_INTERNAL|0x201
  178.     call    EXCEPTION
  179.     pop    %ebx
  180.     jmp    L_exit
  181. #endif PARANOID
  182.  
  183.  
  184. L_exit:
  185.     popl    %ebx
  186.     popl    %edi
  187.     popl    %esi
  188.     leave
  189.     ret
  190.